home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / mus / play / tracker_3_19.lzh / tracker / lookup.c < prev    next >
C/C++ Source or Header  |  1993-11-11  |  6KB  |  255 lines

  1. /* lookup.c */
  2.  
  3. /* A simple database lookup.
  4.  * every entry in the database files is of the form: initial string value
  5.  * We just have to match the initial string, no separators required.
  6.  * Not that the specification just asks for a matching entry, not
  7.  * necessarily the first or the last.
  8.  */
  9. /* $Id: lookup.c,v 1.2 1992/07/22 14:50:25 espie Exp espie $ */
  10.  
  11. /* $Log: lookup.c,v $
  12.  * Revision 1.2  1992/07/22  14:50:25  espie
  13.  * open_file changed, so lookup had to change to incorporate paths as well.
  14.  *
  15.  * Revision 1.1  1992/07/16  17:02:00  espie
  16.  * Initial revision
  17.  *
  18.  *
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <malloc.h>
  24.  
  25. #include "defs.h"
  26. #include "extern.h"
  27.  
  28. LOCAL char *id="$Id";
  29.  
  30. /* the lookup structure is PRIVATE */
  31.  
  32. #define HANDLE 0    /* a null type, for memory handling */
  33. #define FNAME 1     /* a filename, which has not yet been opened */
  34. #define FOPENED 2   /* a file, once opened */
  35. #define STRING 3    /* an already accounted for string */
  36.  
  37. struct lookup
  38.     {
  39.     int type;
  40.     union 
  41.         {
  42.         char *filename;
  43.         FILE *file;
  44.         char *string;
  45.         char *path;
  46.         } value;
  47.     struct lookup *next;
  48.     };
  49.  
  50. /***
  51.  *
  52.  *  lookup memory handling 
  53.  *
  54.  ***/
  55.  
  56. /* link_lookup(base, new): link a new element inside the existing chain */
  57. LOCAL void link_lookup(handle, new)
  58. struct lookup *handle, *new;
  59.     {
  60.     new->next = handle->next;
  61.     handle->next = new;
  62.     }
  63.  
  64. LOCAL void set_lookup(handle, path)
  65. struct lookup *handle;
  66. char *path;
  67.     {
  68.     handle->type = HANDLE;
  69.     handle->value.path = path;
  70.     }
  71.  
  72. /* new = create_lookup(): create an empty element, 
  73.  * chain anchor or to be filled 
  74.  */
  75. struct lookup *create_lookup(path)
  76. char *path;
  77.     {
  78.     struct lookup *new;
  79.  
  80.     new = (struct lookup *)malloc(sizeof(struct lookup));
  81.     if (!new)
  82.         exit(10);
  83.     set_lookup(path);
  84.     new->next = NULL;
  85.     return new;
  86.     }
  87.  
  88. /* free_lookup(handle): free the whole chain. Note that filenames
  89.  * do not belong to us
  90.  */
  91. void free_lookup(handle)
  92. struct lookup *handle;
  93.     {
  94.     struct lookup *to_free;
  95.  
  96.     while(handle)
  97.         {
  98.         to_free = handle;
  99.         handle = handle->next;
  100.         switch(to_free->type)
  101.             {
  102.         case HANDLE:
  103.         case FNAME: /* filenames don't belong to you */
  104.             break;
  105.         case FOPENED:
  106.             close_file(to_free->value.file.fhandle, 
  107.                 to_free->value.file.filetype);
  108.             break;
  109.         case STRING:
  110.             free(to_free->value.string);
  111.             break;
  112.             }
  113.         free(to_free);
  114.         }
  115.     }
  116.  
  117. /* add_lookup(handle, filename): add a new potential filename to the lookup
  118.  * handle
  119.  */
  120. void add_lookup(handle, filename)
  121. struct lookup *handle;
  122. char *filename;
  123.     {
  124.     struct lookup *new;
  125.  
  126.     new = create_lookup();
  127.     new->type = FNAME;
  128.     new->value.filename = filename;
  129.     link_lookup(handle, new);
  130.     }
  131.  
  132.  
  133. /* postfix = check_prefix(template, s):
  134.  * if s is a prefix of template, return the remaining part of template,
  135.  * else return NULL.
  136.  * Note difference between NULL result and empty postfix (pointer to NULL)
  137.  */
  138. static char *check_prefix(template, s)
  139. char *template;
  140. char *s;
  141.     {
  142.     for (; *s; template++, s++)
  143.         /* *s != 0 at that point */
  144.         if (*template != *s)
  145.             return NULL;
  146.     while(*template == ' ' || *template == '\t')
  147.         template++;
  148.     return template;
  149.     }
  150.  
  151. /* copy = create_copy(s): allocate memory and create a copy of string s.
  152.  * get rid of spurious \n at the end.
  153.  */
  154. static char *create_copy(s)
  155. char *s;
  156.     {
  157.     char *new;
  158.     int len;
  159.  
  160.     len = strlen(s);
  161.     while(s[len - 1] == '\n')
  162.         s[--len] = 0;
  163.     new = malloc(len + 1);
  164.     if (!new)
  165.         exit(10);
  166.     return strcpy(new, s);
  167.     }
  168.  
  169. #define BUFSIZE 1500
  170.  
  171. LOCAL char *internal_lookup();
  172.  
  173. /* postfix = lookup(handle, s): lookup string s in the database indexed by
  174.  * handle.
  175.  */
  176. char *lookup(handle, s)
  177. struct lookup *handle;
  178. char *s;
  179.     {
  180.         /* the internal handler also maintains a current path */
  181.     return internal_lookup(handle, s, NULL);
  182.     }
  183.  
  184.  
  185. LOCAL char *internal_lookup(handle, s, path)
  186. struct lookup *handle;
  187. char *s;
  188. char *path;
  189.     {
  190.     char *r;
  191.     static char buffer[BUFSIZE];
  192.     struct lookup *new;
  193.  
  194.     if (handle)
  195.         {
  196.         switch(handle->type)
  197.             {
  198.         case STRING:
  199.             r = check_string(handle->value.string, s);
  200.             if (r)
  201.                 return r;
  202.             else
  203.                 return internal_lookup(handle->next, s, path);
  204.         case HANDLE:
  205.             return internal_lookup(handle->next, s,
  206.                 handle->value.path ? handle->value.path : path);
  207.         case FNAME:
  208.             r = internal_lookup(handle->next, s, path);
  209.             if (r)
  210.                 return r;
  211.             else
  212.                 {
  213.                 if (handle->value.file = 
  214.                     open_file(handle->value.filename, "r", path))
  215.                     {
  216.                     handle->type = FOPENED;
  217.                     return internal_lookup(handle, s, path);
  218.                     }
  219.                 else
  220.                     {
  221.                     set_lookup(handle, NULL);
  222.                     return NULL;
  223.                     }
  224.                 }
  225.         case FOPENED:
  226.             r = internal_lookup(handle->next, s, path);
  227.             if (r)
  228.                 return r;
  229.             else
  230.                 {
  231.                 if (fgets(buffer, BUFSIZE, handle->value.file))
  232.                     {
  233.                     new = create_lookup(NULL);
  234.                     new->type = STRING;
  235.                     new->value.string = create_copy(buffer);
  236.                     link_lookup(handle, new);
  237.                     r = check_prefix(new->value.string, s);
  238.                     if (r)
  239.                         return r;
  240.                     else
  241.                         return internal_lookup(handle, s, path);
  242.                     }
  243.                 else
  244.                     {
  245.                     close_file(handle->value.file);
  246.                     set_lookup(new, NULL);
  247.                     }
  248.                 }
  249.             }
  250.         }
  251.     else
  252.         return NULL;
  253.     }
  254.             
  255.